home *** CD-ROM | disk | FTP | other *** search
/ Nebula 2 / Nebula Two.iso / SourceCode / ObserveTest / ObserveDispatch.m < prev    next >
Text File  |  1995-06-12  |  4KB  |  165 lines

  1. #import <objc/HashTable.h>
  2. #import <objc/Storage.h>
  3. #import <strings.h>
  4.  
  5. #import "ObserveDispatch.h"
  6.  
  7. @implementation ObserveDispatch
  8.  
  9. - init
  10. {
  11.     [super init];
  12.     
  13.     // Create the observers list
  14.     // The key will be the name of the method
  15.     observerTable = [[HashTable alloc] initKeyDesc:"*" valueDesc:"@"];
  16.  
  17.     return self;
  18. }
  19.  
  20. /*
  21. **  Method: initObserver:
  22. **
  23. **  Purpose:  Initialize an observer record that can then be added to the
  24. **        List of observers for an action.  This is a good method for sub-classes
  25. **        to overwrite if they want to accept shorthand action names and turn 
  26. **        them into something more appropriate.
  27. */
  28.  
  29. - initObserver:(observerrec *)anObserver withObject:(id)anObject
  30.     forAction:(char *)anAction withFilter:(char *)aFilter
  31. {
  32.     anObserver->active = YES;
  33.     anObserver->anObject = anObject;
  34.     anObserver->action = NXCopyStringBuffer(anAction);
  35.     anObserver->filter = NXCopyStringBuffer(aFilter);
  36.  
  37.     return self;
  38. }
  39.  
  40. /*
  41.     Method: observerListForAction:
  42.         Returns a list of the observers that are watching for the given
  43.         action.
  44.  
  45.     Return Value:
  46.         Returns the list of observers if there is one or nil otherwise
  47. */
  48.  
  49. - observerListForAction:(char *)anAction
  50. {
  51.     id aList = nil;
  52.  
  53.     aList = (id)[observerTable valueForKey:anAction];
  54.     
  55.     return aList;
  56. }
  57.  
  58. /*
  59.     Method: addObserver:forAction:withFilter:
  60.         This method is the primary interface for adding an observer to 
  61.         a watch list for a given action.
  62.     
  63.     Parameters:
  64.         id anObject        The object that is the observer
  65.         char *actionList    A comma separated list of the actions the observer 
  66.                             wants to watch for.
  67.         char *aFilter    additional information (unused)
  68.  
  69.     Return Value:
  70.         Always returns 0 
  71. */
  72.  
  73. - (int)addObserver:(id)anObject 
  74.     forAction:(char *)actionList 
  75.     withFilter:(char *)aFilter
  76. {
  77.     id aList = nil;
  78.     observerrec newobserver;
  79.         
  80.     #if DBG_ADDSERVER
  81.     printf("ObserveD - addObserver:forAction: %s\n",actionList);
  82.     #endif DBG_ADDSERVER
  83.  
  84.     if (!actionList || !*actionList)
  85.         return -1;
  86.         
  87.     // Create an observer record
  88.     [self initObserver:&newobserver withObject:anObject
  89.         forAction:actionList withFilter:aFilter];
  90.                 
  91.     // Add it to the hash table
  92.     // Look for the list this belongs to
  93.     aList = [self observerListForAction:newobserver.action];
  94.             
  95.     // If not found create it
  96.     if (!aList)
  97.     {
  98.         aList = [[Storage allocFromZone:[self zone]]
  99.             initCount:0
  100.             elementSize:sizeof(observerrec)
  101.             description:"{i@**}"];
  102.         
  103.         // Add the new list to the table of lists
  104.         [observerTable insertKey:NXCopyStringBuffer(newobserver.action) 
  105.             value:aList];
  106.     }
  107.             
  108.     // Add the observer to the list
  109.     [aList addElement:&newobserver];
  110.     
  111.     return NO;
  112. }
  113.  
  114. /*
  115.     Method: addObserver:forAction:
  116.         Same as addObserver:forAction:withFilter:, but passes a blank filter
  117.         by default.
  118.     
  119.     Return Value:
  120.         returns whatever addObserver:forAction:withFilter: returns
  121. */
  122. - (int)addObserver:(id)anObject 
  123.     forAction:(char *)actionList 
  124. {
  125.     return [self addObserver:anObject forAction:actionList withFilter:""];
  126. }
  127.  
  128. /*
  129.     Method: forward::
  130.         
  131.     Return Value:
  132.         always returns self
  133. */
  134.  
  135. - forward:(SEL)aSelector :(marg_list)argFrame
  136. {
  137.     id aList = nil;
  138.     char *selectorName = sel_getName(aSelector);
  139.     
  140.     // Find the list of observers for this method
  141.     // Send the message to each member of the list;
  142.  
  143.     // Dispatch the message to all observers
  144.     aList = [observerTable valueForKey:selectorName];
  145.     if (aList)
  146.     {
  147.         observerrec *anObserver;
  148.         int numObservers = [aList count];
  149.         int counter = 0;
  150.         
  151.         // Now we have the list of observers
  152.         // For each one of them
  153.         for (counter = 0; counter < numObservers; counter++)
  154.         {
  155.             // send out the same message
  156.             anObserver = [aList elementAt:counter];
  157.             [anObserver->anObject performv:aSelector :argFrame];
  158.         }
  159.     }
  160.  
  161.     return self;
  162. }
  163.  
  164.  
  165. @end